package flp.problem;

import java.io.Serializable;

/**
 * Klasa reprezentujaca konkretny problem do rozwiazania.
 * 
 */

public class ProblemInstance implements Serializable
{
    private static final long serialVersionUID = -6224675631699324945L;

    /** Tablica reprezentujaca miejsca gdzie mozna postawic bydynek.*/
    protected BuildingSite buildingSites[];
    /** Tablica duzych portow na rzekach. */
    protected RiverFacility riverFacilities[];
    private BuildingConstraints constraints;
    
    private int requiredInboundCapacity[];
    private int requiredOutboundCapacity[];
    private int requiredCleaningCapacity;
    
    @Override
    public String toString()
    {
        String rep = String.format("C:\n%s\n", constraints);
        for (RiverFacility rf : riverFacilities)
        {
            rep += String.format("RF:\n%s\n", rf);
        }
        for (BuildingSite bs : buildingSites)
        {
            rep += String.format("BS:\n%s\n", bs);
        }
        return rep;
    }
    
    public BuildingConstraints getConstraints() {
        return constraints;
    }
    
    public ProblemInstance(BuildingSite[] buildingSites, RiverFacility[] riverFacilities, BuildingConstraints constraints) {
        this.buildingSites = buildingSites;
        this.riverFacilities = riverFacilities;
        this.constraints = constraints;
        requiredInboundCapacity = new int[this.getRiverFacilitiesCount()];
        requiredOutboundCapacity = new int[this.getRiverFacilitiesCount()];
        computeRequiredCapicity();
    }
    /**zwraca ilosc duzych portow na rzekach. */
    public int getRiverFacilitiesCount() {
        return riverFacilities.length;
    }
        
    /**ilosc stanowisk do zabudowy w Layoucie.*/
    public int getBuildingSitesCount() {
        return buildingSites.length;
    }
        
    /** 
     * Zwraca konkretny BS 
     * (BS.getTransferToCost(int k) aby otrzymac koszt transportu do k) 
     */
    public BuildingSite getBuildingSite(int n) {
        return buildingSites[n];
    }

    public int getRequiredCleaningCapacity() {
        return requiredCleaningCapacity;
    }

    public int getRequiredInboundCapacity(int i) {
        return requiredInboundCapacity[i];
    }

    public int getRequiredOutboundCapacity(int i) {
        return requiredOutboundCapacity[i];
    }
        
    /** 
     * Zwraca konkretny duzy port:
     * getBargesRequiredToNumber(int n, boolean k) -
     * aby otrzymac ilosc statkow plynacych z tego facility do k
     */
    public RiverFacility getRiverFacility(int n) {
        return riverFacilities[n];
    }
    /** moze by tak jednak "Capacity"?
     *  jak pozwalacie mi grzebac w Waszym kodzie, to moge na wlasna reke
     * robic takie refactoringi - freeze
     */
    private void computeRequiredCapicity() {
        for (int i = 0; i < this.getRiverFacilitiesCount(); ++i) {
            for (int j = 0; j < this.getRiverFacilitiesCount(); ++j) {//including siebie - celowo
                requiredInboundCapacity[i] += riverFacilities[i].getBargesRequiredToNumber(j);
                requiredOutboundCapacity[j] += riverFacilities[i].getBargesRequiredToNumber(j);
                requiredCleaningCapacity += riverFacilities[i].getBargesRequiredToNumber(j, true);
            }   
        }
    }
}
